<?php
namespace app\backend\library;

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\db\exception\DbException;
use think\facade\Db;

class JwtAuth
{
    private static $key;

    //默认 Token 令牌秘钥
    const DEFAULT_SECRET_KEY = 'aK$d[1d&sDv3945^8E!he}toqxs~';

    const DEFAULT_APP_HOST = '127.0.0.1';

    public static function init()
    {
        if (!self::$key) {
            self::$key = config('set.jwt.secret_key', self::DEFAULT_SECRET_KEY);
        }
    }

    /**
     * 生成Access Token
     * @param $uid
     * @param $expire
     * @return string
     */
    public static function createAccessToken($uid, $expire = 1800)
    {
        self::init();
        $payload = [
            'iss' => config('app.app_host', self::DEFAULT_APP_HOST),
            'aud' => 'client',
            'iat' => time(),
            'exp' => time() + $expire,
            'data' => [
                'user_id' => $uid,
                'token_type' => 'access'
            ]
        ];
        return JWT::encode($payload, self::$key, 'HS256');
    }

    /**
     * 生成Refresh Token
     * @param $uid
     * @param $expire
     * @return string
     */
    public static function createRefreshToken($uid, $expire = 604800)
    {
        self::init();
        $payload = [
            'iss' => config('app.app_host', self::DEFAULT_APP_HOST),
            'aud' => 'client',
            'iat' => time(),
            'exp' => time() + $expire,
            'data' => [
                'user_id' => $uid,
                'token_type' => 'refresh'
            ]
        ];
        $token = JWT::encode($payload, self::$key, 'HS256');

        // 存储Refresh Token
        Db::name('admin_refresh_token')->insert([
            'user_id' => $uid,
            'token' => $token,
            'expire_time' => time() + $expire,
            'created_at' => date("Y-m-d H:i:s")
        ]);

        return $token;
    }

    /**
     * 验证Token
     * @param $token
     * @return array|false|string[]
     */
    public static function verifyToken($token)
    {
        self::init();
        try {
            $decoded = JWT::decode($token, new Key(self::$key, 'HS256'));
            return (array)$decoded->data;
        } catch (\Firebase\JWT\ExpiredException $e) {
            // 特殊处理过期异常
            return ['error' => 'token_expired'];
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 验证Refresh Token
     * @param $token
     * @return false|mixed
     */
    public static function verifyRefreshToken($token)
    {
        self::init();
        try {
            $decoded = JWT::decode($token, new Key(self::$key, 'HS256'));
            $data = (array)$decoded->data;

            // 检查Token类型
            if ($data['token_type'] !== 'refresh') {
                return false;
            }

            // 检查数据库中的Refresh Token
            $exists = Db::name('admin_refresh_token')
                ->where('token', $token)
                ->where('expire_time', '>', time())
                ->where('user_id', $data['user_id'])
                ->find();

            return $exists ? $data['user_id'] : false;
        } catch (\Exception $e) {
            return false;
        }
    }

    /**
     * 撤销Refresh Token
     * @param $token
     * @return void
     * @throws DbException
     */
    public static function revokeRefreshToken($token)
    {
        Db::name('admin_refresh_token')
            ->where('token', $token)
            ->delete();
    }

    /**
     * 获取Token中的用户ID（不验证）
     * @param $token
     * @return false
     */
    public static function getUserIdFromToken($token)
    {
        try {
            $tks = explode('.', $token);
            if (count($tks) != 3) return false;

            $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($tks[1]));
            return $payload->data->user_id ?? false;
        } catch (\Exception $e) {
            return false;
        }
    }
}